import json

import redis
from utils.utils import to_text

from .const import RedisConst


class BaseStorage:

    def __init__(self, client, prefix):
        for method_name in ('get', 'set', 'delete'):
            assert hasattr(client, method_name)
        self.client = client
        self.prefix = prefix

    def key_name(self, key):
        return '{0}:{1}'.format(self.prefix, key)

    def get(self, key, default=None):
        key = self.key_name(key)
        value = self.client.get(key)
        if value is None:
            return default
        return json.loads(to_text(value))

    def set(self, key, value, ttl=None):
        if value is None:
            return
        key = self.key_name(key)
        value = json.dumps(value)
        self.client.set(key, value, ex=ttl)

    def delete(self, key):
        key = self.key_name(key)
        self.client.delete(key)


class RedisStorage(BaseStorage):
    def __init__(self, client, prefix):
        super(RedisStorage, self).__init__(client, prefix)

    def incr(self, key, amount=1):
        key = self.key_name(key)
        self.client.incr(key, amount)

    def expire(self, key, expire):
        key = self.key_name(key)
        self.client.expire(key, expire)


class RedisClient:
    def __init__(self, prefix=RedisConst.REDIS_PREFIX):
        self.prefix = prefix
        self.redis_pool = redis.BlockingConnectionPool(host=RedisConst.REDIS_HOST,
                                                       port=RedisConst.REDIS_PORT,
                                                       password=RedisConst.REDIS_PASSWORD,
                                                       db=RedisConst.REDIS_DB)

    def client(self):
        return RedisStorage(redis.StrictRedis(connection_pool=self.redis_pool), prefix=self.prefix)
